import {Point} from './bezier';
export class Draw{
    static staticCode:number = 0;
    static ZPI:number = Math.PI * 2;
    static canvas:HTMLCanvasElement = document.createElement('canvas');
    static ctx:CanvasRenderingContext2D = Draw.canvas.getContext('2d', {alpha: false});
    canvas:HTMLCanvasElement = document.createElement('canvas');
    ctx:CanvasRenderingContext2D;
    width:number = 100;
    height:number = 100;
    originX:number = 0;
    originY:number = 0;
    radius:number = 6;
    constructor(containerId:string, options?:object){
        let container = document.getElementById(containerId);
        if(!container) throw Error('Can not found Element by ID paramater as "'+containerId+'", in constructor of "Draw"');
        let cv = this.canvas;
        if(!container.style.position){
            container.style.position = 'relative';
        }
        Object.defineProperties(this, {
            width: {
                set(width){
                    if(width !== cv.width){
                        container.style.width = width + 'px';
                        cv.width = width;
                        Draw.canvas.width = width;
                    }
                },
                get(){
                    return cv.width;
                }
            },
            height: {
                set(height){
                    if(height !== cv.height){
                        container.style.height = height + 'px';
                        cv.height = height;
                        Draw.canvas.height = height;
                    }
                },
                get(){
                    return cv.height;
                }
            },
            ctx: {
                configurable: false,
                enumerable: false,
                writable: false,
                value: cv.getContext('2d', { alpha: false })
            }
        });
        this.width = cv.width;
        this.height = cv.height;
        Object.assign(this, options);
        container.appendChild(cv);
    }
    bgOn(){
        Draw.staticCode = 1;
        this.clear();
    }
    bgOff(){
        Draw.staticCode = 0;
        this.clear();
    }
    bg(){
        Draw.staticCode = 0;
        this.ctx.drawImage(Draw.canvas, 0, 0, this.width, this.height);
    }
    _ctx(){
        return Draw.staticCode === 1 ? Draw.ctx : this.ctx;
    }
    x(x:number){
        return Math.round(x + this.originX);
    }
    y(y:number){
        return Math.round(this.height - y - this.originY);
    }
    axis(options?:any){
        let ctx = this._ctx();
        if(options && options.x !== undefined) this.originX = options.x;
        if(options && options.y !== undefined) this.originY = options.y;
        ctx.save();
        if(options && options.lineWidth)ctx.lineWidth = options.lineWidth;
        if(options && options.strokeStyle)ctx.strokeStyle = options.strokeStyle;
        let arrowSize = options && options.arrowSize ? options.arrowSize : 10;
        ctx.beginPath();
        //X轴三角箭头
        ctx.moveTo(this.width, this.height-this.originY);
        ctx.lineTo(this.width-arrowSize, this.height-this.originY-arrowSize/2);
        ctx.lineTo(this.width-arrowSize, this.height-this.originY+arrowSize/2);
        ctx.lineTo(this.width, this.height-this.originY);
        //X轴
        ctx.lineTo(this.originX, this.height-this.originY);
        //Y轴
        ctx.lineTo(this.originX, 0);
        //Y轴三角箭头
        ctx.lineTo(this.originX-arrowSize/2, arrowSize);
        ctx.lineTo(this.originX+arrowSize/2, arrowSize);
        ctx.lineTo(this.originX, 0);
        ctx.stroke();
        ctx.restore();
    }
    grid(between:number = 50, strokeStyle:string = '#bbb'){
        let ctx = this._ctx(), x = this.originX + between, y = this.height - this.originY;
        ctx.save();
        ctx.beginPath();
        if(strokeStyle) ctx.strokeStyle = strokeStyle;
        for(;x < this.width - this.originX; x += between){
            ctx.moveTo(x, y);
            ctx.lineTo(x, 0);
        }
        for(y -= between; y > 0; y -= between){
            ctx.moveTo(this.originX, y);
            ctx.lineTo(this.width, y);
        }
        ctx.stroke();
        ctx.restore();
    }
    bezierN(points:number[], strokeStyle?:string, lineWidth?:number){
        let ctx = this._ctx();
        let len = points.length;
        if(len < 4) return;
        ctx.save();
        if(strokeStyle) ctx.strokeStyle = strokeStyle;
        if(lineWidth) ctx.lineWidth = lineWidth;
        ctx.beginPath();
        ctx.moveTo(this.x(points[0]), this.y(points[1]));
        switch(len){
            case 4:
                ctx.lineTo(this.x(points[2]), this.y(points[3]));
            break;
            case 6:
                ctx.quadraticCurveTo(this.x(points[2]), this.y(points[3]), this.x(points[4]), this.y(points[5]));
            break;
            case 8:
                ctx.bezierCurveTo(this.x(points[2]),this.y(points[3]), this.x(points[4]), this.y(points[5]), this.x(points[6]), this.y(points[7]));
            break;
            default:
                for(let i=0; i<1; i+=0.01){
                    let arr = Point.get(points, i);
                    ctx.lineTo(this.x(arr[0]), this.y(arr[1]));
                }
        }
        ctx.stroke();
        ctx.restore();
    }
    // bezier3N(points:number[], strokeStyle?:string, lineWidth?:number){
    //     let ctx = this._ctx();
    //     let len = points.length;
    //     ctx.save();
    //     if(strokeStyle) ctx.strokeStyle = strokeStyle;
    //     if(lineWidth) ctx.lineWidth = lineWidth;
    //     ctx.beginPath();

    //     ctx.stroke();
    //     ctx.restore();
    // }
    circle(points:number[], r?:number, fillStyle?:string, strokeStyle?:string, lineWidth?:number){
        let ctx = this._ctx();
        r = r || this.radius;
        ctx.save();
        if(strokeStyle) ctx.strokeStyle = strokeStyle;
        if(fillStyle) ctx.fillStyle = fillStyle;
        if(lineWidth) ctx.lineWidth = lineWidth;
        for(let i=0,len=points.length; i<len; i+=2){
            if(points[i+1] === undefined) break;
            ctx.beginPath();
            ctx.arc(this.x(points[i]), this.y(points[i+1]), r, 0, Draw.ZPI);
            if(fillStyle) ctx.fill();
            else ctx.stroke();
        }
        ctx.restore();
    }
    pline(points:number[], strokeStyle?:string, lineWidth?:number){
        let ctx = this._ctx();
        ctx.save();
        if(strokeStyle) ctx.strokeStyle = strokeStyle;
        if(lineWidth) ctx.lineWidth = lineWidth;
        ctx.beginPath();
        ctx.moveTo(this.x(points[0]), this.y(points[1]));
        for(let i=2,len=points.length; i<len; i+=2){
            ctx.lineTo(this.x(points[i]), this.y(points[i+1]));
        }
        ctx.stroke();
        ctx.restore();
    }
    clear(color?:string){
        let ctx = this._ctx();
        if(color){
            ctx.fillStyle = color;
  		    ctx.fillRect(0, 0, this.width, this.height);
        }else{
            ctx.clearRect(0, 0, this.width, this.height);
        }
    }
}